#include "ptm.h"

PTMWidget::PTMWidget (QWidget* parent) : QTableWidget (parent) {
    setLayoutDirection (Qt::LeftToRight);
    setEditTriggers (QTableWidget::NoEditTriggers);
    setSelectionMode (QTableWidget::SingleSelection);
    setSelectionBehavior (QTableWidget::SelectRows);
    QStringList columnLabels;
    columnLabels.push_back ("Start time");
    columnLabels.push_back ("Duration");
    columnLabels.push_back ("Title");
    columnLabels.push_back ("Author");
    columnLabels.push_back ("Link");
    setColumnCount (columnLabels.size ());
    setHorizontalHeaderLabels (columnLabels);
    setColumnHidden (4, true);
}

PTMWidget::~PTMWidget (void) {

}

bool PTMWidget::setDisabledRows (const unsigned int startRow, const unsigned int endRow) {
    bool result = false;
    if (startRow <= endRow && endRow < (unsigned int) rowCount ()) {
        for (unsigned int i = startRow; i <= endRow; ++i) {
            verticalHeaderItem(i)->setFlags (Qt::NoItemFlags);
            for (unsigned int j = 0, count = (unsigned int) columnCount (); j < count; ++j) {
                item (i, j)->setFlags (Qt::NoItemFlags);
            }
        }
        result = true;
    }
    return (result);
}

bool PTMWidget::setEnabledRows (const unsigned int startRow, const unsigned int endRow) {
    bool result = false;
    if (startRow <= endRow && endRow < (unsigned int) rowCount ()) {
        for (unsigned int i = startRow; i <= endRow; ++i) {
            verticalHeaderItem(i)->setFlags (Qt::ItemIsEnabled | Qt::ItemIsSelectable);
            for (unsigned int j = 0, count = (unsigned int) columnCount (); j < count; ++j) {
                item (i, j)->setFlags (Qt::ItemIsEnabled | Qt::ItemIsSelectable);
            }
        }
        result = true;
    }
    return (result);
}

void PTMWidget::incEventDuration (const unsigned int row, const unsigned int minutes) {
    QTableWidgetItem* event = item (row, 1);
    event->setText (QString::number (event->text ().toInt () + minutes));
    for (unsigned int i = row + 1, size = rowCount (); i < size; ++i) {
        event = item (i, 0);
        QTime eventStartTime = QTime::fromString (event->text ());
        eventStartTime = eventStartTime.addSecs (minutes * 60);
        event->setText (eventStartTime.toString ().left (5));
    }
}

bool PTMWidget::baseTimeToCurrentTime (unsigned int row) {
    bool result = false;
    if (row < (unsigned int) rowCount ()) {
        baseTime = QTime::currentTime ();
        unsigned int eventsDuration = 0;
        for (unsigned int i = row, size = (unsigned int) rowCount (); i < size; ++i) {
            item (i, 0)->setText ((baseTime.addSecs (eventsDuration * 60)).toString ().left (5));
            eventsDuration += item (i, 1)->text ().toInt ();
        }
        result = true;
    }
    return (result);
}

bool PTMWidget::loadFromXML (const QString& filePath) {
    clear ();

    XMLReader handler (this, filePath);
    return (handler.isRead ());
}

bool PTMWidget::saveToXML (const QString& filePath) {
    XMLWriter writer (this, filePath);
    return (writer.isWrite ());
}

const QString& PTMWidget::getName (void) const {
    return (name);
}

bool PTMWidget::setName (const QString& name) {
    bool result = false;
    if (!name.isNull () && !name.isEmpty ()) {
        this->name = name;
        result = true;
    }
    return (result);
}

bool PTMWidget::setBaseTime (const QTime& baseTime) {
    return (this->baseTime.setHMS (baseTime.hour (), baseTime.minute (), 0));
}

const QTime& PTMWidget::getBaseTime (void) const {
    return (baseTime);
}

PTMWidget::XMLWriter::XMLWriter (PTMWidget* ptmWidget, const QString& filePath, const QString& codec) {
    writeResult = false;
    QDomDocument doc;
    QDomNode xmlNode = doc.createProcessingInstruction ("xml", "version=\"1.0\" encoding=\"" + codec + "\"");
    doc.appendChild (xmlNode);
    QDomElement  head = doc.createElement ("PTM");
    head.setAttribute ("name", ptmWidget->getName ());
    head.setAttribute ("version", "1.0");
    doc.appendChild (head);
    QDomElement  baseTime = doc.createElement ("base_time");
    baseTime.setAttribute ("value", ptmWidget->getBaseTime ().toString ().left (5));
    head.appendChild (baseTime);

    for (int i = 0, size = ptmWidget->rowCount (); i < size; ++i) {
        QDomElement event = doc.createElement ("event");
        QString type = ptmWidget->verticalHeaderItem (i)->text ().toLower ();
        event.setAttribute ("type", type);
        event.setAttribute ("duration", ptmWidget->item (i, 1)->text ());
        if (type.compare ("presentation") == 0) {
            event.setAttribute ("title", ptmWidget->item (i, 2)->text ());
            event.setAttribute ("author", ptmWidget->item (i, 3)->text ());
            event.setAttribute ("link", "auto");
        }
        head.appendChild (event);
    }
    QFile file (filePath);
    if (file.open (QIODevice::WriteOnly)) {
        QTextStream out (&file);
        out.setCodec (codec.toAscii ());
        doc.save (out, 2);
        file.close ();
        writeResult = true;
    }
}

void PTMWidget::clear (void) {
    for (int start = rowCount () - 1, end = 0; start >= end; --start) {
        removeRow (start);
    }
    setName (QString::null);
    setBaseTime (QTime ());
}

bool PTMWidget::XMLWriter::isWrite (void) const {
    return (writeResult);
}
bool PTMWidget::XMLReader::isRead (void) const {
    return (readResult);
}

PTMWidget::XMLReader::XMLReader (PTMWidget* ptmWidget, const QString& filePath) {
    this->ptmWidget = ptmWidget;
    presentationCount = 0;
    readResult = false;
    eventDuration = 0;
    if (QFile::exists (filePath)) {
        QFileInfo fileInfo (filePath);
        if (fileInfo.fileName ().compare ("_ptm.xml") == 0 && fileInfo.isReadable ()) {
            QFile file (filePath);
            this->xmlDirectory = fileInfo.absolutePath ();
            QXmlSimpleReader reader;
            reader.setContentHandler (this);
            readResult = reader.parse (&file);
            if (!readResult) {
                ptmWidget->clear ();
            }
        }
    }
}

bool PTMWidget::XMLReader::characters (const QString& str)
{
    currentText += str;
    return (true);
}

bool PTMWidget::XMLReader::startElement (const QString& , const QString& , const QString& qName, const QXmlAttributes& attribs) {
    readResult = false;
    if (qName == "PTM") {
        QString xmlFormatVersion = attribs.value ("version");
        if (xmlFormatVersion.compare ("1.0") == 0) {
            readResult = ptmWidget->setName (attribs.value ("name"));
        }
    }
    else {
        if (qName == "base_time") {
            readResult = ptmWidget->setBaseTime (QTime::fromString (attribs.value ("value"), "hh:mm"));
        }
        else {
            if (qName == "event") {
                QString type = attribs.value ("type");
                if (!type.isEmpty ()) {
                    QString buffer = attribs.value ("duration");
                    if (!buffer.isEmpty ()) {
                        int duration = buffer.toInt ();
                        if (duration >= -1) {
                            QString title = attribs.value ("title");
                            QString author = attribs.value ("author");
                            QString link = attribs.value ("link");
                            readResult = elementEvent (type, duration, title, author, link);
                        }
                    }
                }
            }
        }
    }
    return (readResult);
}

bool PTMWidget::XMLReader::elementEvent (const QString& type, const int duration, const QString& title, const QString& author, const QString& link) {
    bool result = false;
    QString generatedLink = link;
    if (type.compare ("begin") == 0) {
        generatedLink = xmlDirectory + "/_begin.jpg";
    }
    else {
        if (type.compare ("break") == 0) {
            generatedLink = xmlDirectory + "/_break.jpg";
        }
        else {
            if (type.compare ("end") == 0) {
                generatedLink = xmlDirectory + "/_end.jpg";
            }
            else {
                if (type.compare ("presentation") == 0 && link.compare ("auto") == 0 && !title.isEmpty () && !author.isEmpty ()) {
                    QString number;
                    presentationCount ++;
                    number.setNum (presentationCount);
                    if (presentationCount < 10) {
                        number.push_front ("0");
                    }
                    generatedLink = xmlDirectory + '/' + number + "_PanelDiscussion.ppt";

                }
                else {
                    return (result);
                }
            }
        }
    }
    if (QFile::exists (generatedLink)) {
        int eventCount = ptmWidget->rowCount ();
        ptmWidget->setRowCount (eventCount + 1);
        QTime time = ptmWidget->getBaseTime ();
        time = time.addSecs (60 * eventDuration);
        eventDuration += duration;
        QString label = type;
        label [0] = label [0].toUpper ();
        ptmWidget->setVerticalHeaderItem (eventCount, new QTableWidgetItem (label));
        ptmWidget->setItem (eventCount, 0, new QTableWidgetItem (time.toString ().left (5)));
        ptmWidget->setItem (eventCount, 1, new QTableWidgetItem (QString::number (duration)));
        ptmWidget->setItem (eventCount, 2, new QTableWidgetItem (title));
        ptmWidget->setItem (eventCount, 3, new QTableWidgetItem (author));
        ptmWidget->setItem (eventCount, 4, new QTableWidgetItem (generatedLink));
        result = true;
    }
    return (result);
}
